import pandas as pd
import numpy as np
import plotly.express as px
from nicegui import ui
from scipy.interpolate import griddata
import plotly.graph_objects as go
import scipy.stats as stats


# 加载数据
def load_data():
    try:
        df = pd.read_csv('Airbnb_Open_Data.csv', low_memory=False)
        print("原始数据形状:", df.shape)
        return df
    except FileNotFoundError:
        print("文件未找到，使用示例数据...")
        np.random.seed(42)
        df = pd.DataFrame({
            'id': range(1, 1001),
            'NAME': [f'房源{i}' for i in range(1, 1001)],
            'host name': [f'房东{i % 100}' for i in range(1, 1001)],
            'neighbourhood group': np.random.choice(['曼哈顿', '布鲁克林', '皇后区', '布朗克斯', '史泰登岛'], 1000),
            'neighbourhood': ['社区' + str(i % 50) for i in range(1, 1000)],
            'country': ['美国'] * 1000,
            'instant_bookable': np.random.choice([True, False], 1000),
            'cancellation_policy': np.random.choice(['灵活', '中等', '严格'], 1000),
            'room type': np.random.choice(['整套房源', '私人房间', '共享房间'], 1000),
            'Construction year': np.random.randint(1900, 2023, 1000),
            'latitude': np.random.uniform(40.49, 40.92, 1000),
            'longitude': np.random.uniform(-74.26, -73.70, 1000),
            'price': np.random.normal(150, 75, 1000).clip(20, 1000),
            'service fee': np.random.normal(30, 15, 1000).clip(0, 200),
            'minimum nights': np.random.randint(1, 30, 1000),
            'number of reviews': np.random.poisson(20, 1000),
            'review rate number': np.random.normal(4.2, 0.5, 1000).clip(1, 5).round(1),
            'calculated host listings count': np.random.randint(1, 50, 1000),
            'availability 365': np.random.randint(0, 365, 1000)
        })
        return df


# 数据清洗
def clean_data(df):
    if df is None: return None

    print("可用列名:", df.columns.tolist())

    # 去重
    df.drop_duplicates(inplace=True)

    # 处理缺失值
    fill_rules = {
        'NAME': 'Unknown',
        'host name': 'Unknown',
        'neighbourhood group': 'Unknown',
        'neighbourhood': 'Unknown',
        'country': 'Unknown',
        'instant_bookable': 'False',
        'cancellation_policy': 'Unknown',
        'room type': 'Unknown',
        'Construction year': df['Construction year'].median() if 'Construction year' in df else 2000,
        'minimum nights': df['minimum nights'].median() if 'minimum nights' in df else 1,
        'number of reviews': 0,
        'review rate number': df['review rate number'].median() if 'review rate number' in df else 4.0,
        'calculated host listings count': df[
            'calculated host listings count'].median() if 'calculated host listings count' in df else 1,
        'availability 365': df['availability 365'].median() if 'availability 365' in df else 365,
        'latitude': df['latitude'].median() if 'latitude' in df else 40.7128,
        'longitude': df['longitude'].median() if 'longitude' in df else -74.0060
    }
    for col, val in fill_rules.items():
        if col in df.columns:
            df[col] = df[col].fillna(val)
        elif isinstance(val, (int, float, str)):
            df[col] = val

    # 清理价格列
    for col in ['price', 'service fee']:
        if col in df.columns:
            df = df.copy()
            df[col] = df[col].astype(str).str.replace(r'[^\d.]', '', regex=True)
            df[col] = df[col].replace('', 0).astype(float)
            df = df[(df[col] > 0) & (df[col] < 10000) if col == 'price' else (df[col] >= 0) & (df[col] < 1000)]

    # 清理建造年份
    if 'Construction year' in df.columns:
        df = df[(df['Construction year'] >= 1800) & (df['Construction year'] <= 2023)]
        df['Construction year'] = df['Construction year'].astype(int)

    print("清洗后数据形状:", df.shape)
    cleaned_file = 'cleaned_airbnb_data.csv'
    df.to_csv(cleaned_file, index=False)
    print(f"清洗后的数据已保存至: {cleaned_file}")
    return df


# 数据分析
def analyze_data(df):
    if df is None: return None, None, None, None

    # 按行政区分组
    neighborhood_stats = df.groupby('neighbourhood group').agg(
        listing_count=('id', 'count'),
        avg_price=('price', 'mean'),
        avg_review=('review rate number', 'mean')
    ).reset_index()

    # 按房型分组
    room_type_stats = df.groupby('room type').agg(
        listing_count=('id', 'count'),
        avg_price=('price', 'mean'),
        avg_review=('review rate number', 'mean')
    ).reset_index()

    # 数据集统计分析
    numeric_cols = df.select_dtypes(include=[np.number]).columns
    stats_results = {}

    for col in numeric_cols:
        col_data = df[col].dropna()
        if len(col_data) > 0:
            stats_results[col] = {
                'count': len(col_data),
                'mean': np.mean(col_data),
                'median': np.median(col_data),
                'std': np.std(col_data),
                'variance': np.var(col_data),
                'min': np.min(col_data),
                '25%': np.percentile(col_data, 25),
                '50%': np.percentile(col_data, 50),
                '75%': np.percentile(col_data, 75),
                'max': np.max(col_data),
                'skewness': stats.skew(col_data),
                'kurtosis': stats.kurtosis(col_data),
                'normality_p': stats.normaltest(col_data).pvalue if len(col_data) > 8 else None,
                'is_normal': stats.normaltest(col_data).pvalue > 0.05 if len(col_data) > 8 else None
            }

    return neighborhood_stats, room_type_stats, df, stats_results


# 可视化函数
def plot_price_distribution(df):
    return px.box(
        df, x='neighbourhood group', y='price',
        title='各行政区房源价格分布',
        labels={'neighbourhood group': '行政区', 'price': '价格($)'}
    )


def plot_room_type_price(df):
    return px.sunburst(
        df, path=['neighbourhood group', 'room type'], values='price',
        title='行政区与房型价格分布', color='review rate number',
        color_continuous_scale='RdBu', range_color=[3, 5]
    )


def plot_price_review(df):
    if len(df) < 50 or 'price' not in df.columns or 'review rate number' not in df.columns or 'number of reviews' not in df.columns:
        return go.Figure().update_layout(title="数据不足，无法生成曲面图")
    # 为曲面图生成网格数据
    x = np.linspace(df['price'].min(), df['price'].max(), 20)
    y = np.linspace(df['review rate number'].min(), df['review rate number'].max(), 20)
    X, Y = np.meshgrid(x, y)
    # 使用griddata进行插值
    points = df[['price', 'review rate number']].values
    values = df['number of reviews'].values
    Z = griddata(points, values, (X, Y), method='cubic', fill_value=0)
    fig = go.Figure(data=[go.Surface(z=Z, x=x, y=y, colorscale='Viridis')])
    fig.update_layout(
        title='价格、评分与平均评论数曲面图',
        scene=dict(
            xaxis_title='价格($)',
            yaxis_title='评分(1-5)',
            zaxis_title='平均评论数'
        ),
        height=600,
        plot_bgcolor='rgba(248, 250, 252, 1)',
        paper_bgcolor='rgba(255, 255, 255, 1)',
        font=dict(family="Inter, sans-serif")
    )
    return fig


def plot_filtered_summary(df):
    if len(df) == 0:
        return px.bar(title="无筛选结果")

    # 按行政区统计筛选后房源数量
    summary = df.groupby('neighbourhood group')['id'].count().reset_index()
    summary.columns = ['neighbourhood group', 'filtered_count']

    return px.bar(
        summary, x='neighbourhood group', y='filtered_count',
        title='筛选结果 - 各行政区房源数量',
        labels={'neighbourhood group': '行政区', 'filtered_count': '筛选后房源数'}
    )


def plot_statistical_analysis(stats_results):
    if not stats_results:
        return go.Figure().update_layout(title="无统计数据可用")

    # 创建统计指标表格
    stats_df = pd.DataFrame.from_dict(stats_results, orient='index')
    stats_df.reset_index(inplace=True)
    stats_df.rename(columns={'index': '指标'}, inplace=True)

    # 选择要显示的列
    display_cols = ['mean', 'median', 'std', 'variance', 'min', '25%', '50%', '75%', 'max', 'skewness', 'kurtosis']

    fig = go.Figure(data=[go.Table(
        header=dict(
            values=['指标'] + [col for col in display_cols if col in stats_df.columns],
            fill_color='paleturquoise',
            align='left'
        ),
        cells=dict(
            values=[stats_df['指标']] + [stats_df[col].round(4) for col in display_cols if col in stats_df.columns],
            fill_color='lavender',
            align='left'
        ))
    ])

    fig.update_layout(
        title='数据集统计分析',
        height=600,
        margin=dict(l=20, r=20, t=60, b=20)
    )

    return fig


# 创建数据表格
def create_data_table(data, container):
    # 清除容器原有内容
    container.clear()

    # 准备列定义
    columns = [
        {'name': 'id', 'label': 'ID', 'field': 'id', 'required': True, 'align': 'left'},
        {'name': 'NAME', 'label': '名称', 'field': 'NAME', 'align': 'left'},
        {'name': 'neighbourhood group', 'label': '行政区', 'field': 'neighbourhood group', 'align': 'left'},
        {'name': 'neighbourhood', 'label': '社区', 'field': 'neighbourhood', 'align': 'left'},
        {'name': 'room type', 'label': '房型', 'field': 'room type', 'align': 'left'},
        {'name': 'price', 'label': '价格', 'field': 'price', 'align': 'right'},
        {'name': 'review rate number', 'label': '评分', 'field': 'review rate number', 'align': 'right'},
        {'name': 'number of reviews', 'label': '评论数', 'field': 'number of reviews', 'align': 'right'}
    ]

    # 转换数据为表格格式
    items = data[['id', 'NAME', 'neighbourhood group', 'neighbourhood', 'room type', 'price',
                  'review rate number', 'number of reviews']].to_dict('records')
    # 限制显示数量
    max_display = 500
    if len(items) > max_display:
        with container:
            ui.label(f"显示前 {max_display} 条记录，共 {len(items)} 条记录").classes('text-sm text-gray-500 mb-2')
            items = items[:max_display]
    # 创建表格
    with container:
        table = ui.table(
            columns=columns,
            rows=items,
            row_key='id',
            pagination={'rowsPerPage': 10},
        ).classes('w-full h-[550px]')

        # 添加分页控制
        ui.pagination(
            min=1,
            max=max(1, len(items) // 10 + (1 if len(items) % 10 else 0)),
            on_change=lambda e: table.props(f'pagination={{page: {e.value}, rowsPerPage: 10}}')
        )


# 创建界面
def create_web_interface():
    df = load_data()
    if df is None: return
    df = clean_data(df)
    neighborhood_stats, room_type_stats, full_df, stats_results = analyze_data(df)
    # 存储当前筛选后的数据
    current_filtered_df = full_df.copy()
    # 添加全局样式
    ui.add_head_html('''
    <style>
        body {
            display: flex;
            margin: 0;
            padding: 0;
            font-family: 'Inter', sans-serif;
        }
        .sidebar {
            width: 15%;
            height: 100vh;
            background-color: #f8fafc;
            box-shadow: 1px 0 4px rgba(0,0,0,0.1);
            overflow-y: auto;
            padding: 16px;
            position: fixed;
            top: 0;
            left: 0;
            z-index: 100;
        }
        .main-content {
            margin-left: 250px;
            padding: 24px;
            width: 85%;
        }
        .card {
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.08);
            padding: 16px;
            margin-bottom: 16px;
        }
        .nav-item {
            padding: 12px 16px;
            margin-bottom: 8px;
            border-radius: 6px;
            cursor: pointer;
            transition: background 0.2s;
        }
        .nav-item:hover, .nav-item.active {
            background-color: #e5e7eb !important;
        }
        .plot-container {
            margin-bottom: 24px;
        }
        .dataset-intro {
            background: #ebf8ff;
            border-left: 4px solid #3182ce;
            padding: 12px 16px;
            border-radius: 0 4px 4px 0;
            margin-bottom: 16px;
        }
        .stat-card {
            background: #f0fdf4;
            border-left: 4px solid #10b981;
            padding: 12px 16px;
            border-radius: 0 4px 4px 0;
            margin-bottom: 16px;
        }
    </style>
    ''')
    # 左侧边栏
    with ui.element('div').classes('sidebar'):
        # 标题
        ui.label('Airbnb数据分析').classes('text-2xl font-bold mb-4')
        # 数据集介绍卡片
        with ui.element('div').classes('dataset-intro'):
            ui.label('关于数据集').classes('text-lg font-semibold mb-2')
            ui.markdown('''
            Airbnb是一个在线住宿市场，主要提供度假租赁和旅游活动的寄宿家庭服务。该数据集描述了纽约市寄宿家庭的房源活动。

            **数据包含:**
            - 房源信息及评价分数
            - 评价详情
            - 日历和价格信息

            **数据来源:** [Inside Airbnb](http://insideairbnb.com/explore/)
            ''').classes('text-sm')
        # 数据概览卡片
        with ui.card():
            ui.label('数据概览').classes('text-lg font-semibold mb-2')
            with ui.column():
                ui.label(f"总房源数: {len(full_df)}").classes('text-sm')
                ui.label(f"行政区数: {len(full_df['neighbourhood group'].unique())}").classes('text-sm')
                ui.label(f"平均价格: ${full_df['price'].mean():.2f}").classes('text-sm')
                ui.label(f"平均评分: {full_df['review rate number'].mean():.2f}/5").classes('text-sm')
        # 导航菜单
        ui.label('数据分析').classes('text-lg font-semibold mb-2')
        with ui.column():
            # 声明全局导航按钮和内容容器
            global price_content, room_content, review_content, filtered_content, data_content, stats_content
            global price_btn, room_btn, review_btn, filtered_btn, data_btn, stats_btn
            global plotly1, plotly2, plotly3, plotly_filtered, plotly_stats, table_container
            # 价格分布按钮
            price_btn = ui.button('价格分布', on_click=lambda: show_content('price')) \
                .classes('nav-item active flex items-center justify-start w-full text-left') \
                .props(' flat ')
            # 房型分析按钮
            room_btn = ui.button('房型分析', on_click=lambda: show_content('room')) \
                .classes('nav-item flex items-center justify-start w-full text-left') \
                .props('flat ')
            # 评分关联按钮
            review_btn = ui.button('评分关联', on_click=lambda: show_content('review')) \
                .classes('nav-item flex items-center justify-start w-full text-left') \
                .props('flat ')
            # 筛选结果按钮
            filtered_btn = ui.button('筛选结果', on_click=lambda: show_content('filtered')) \
                .classes('nav-item flex items-center justify-start w-full text-left') \
                .props('flat ')
            # 数据详情按钮
            data_btn = ui.button('数据详情', on_click=lambda: show_content('data')) \
                .classes('nav-item flex items-center justify-start w-full text-left') \
                .props('flat ')
            # 统计分析按钮
            stats_btn = ui.button('统计分析', on_click=lambda: show_content('stats')) \
                .classes('nav-item flex items-center justify-start w-full text-left') \
                .props('flat ')
    # 主内容区域
    with ui.element('div').classes('main-content'):
        # 价格分布内容（默认显示）
        with ui.element('div').classes('content-block').style('display: block') as price_content:
            ui.label('各行政区房源价格分布').classes('text-2xl font-bold mb-4')
            plotly1 = ui.plotly(plot_price_distribution(full_df)).classes('w-full h-96')
        # 房型分析内容（默认隐藏）
        with ui.element('div').classes('content-block').style('display: none') as room_content:
            ui.label('行政区与房型价格分布').classes('text-2xl font-bold mb-4')
            plotly2 = ui.plotly(plot_room_type_price(full_df)).classes('w-full h-96')
        # 评分关联内容（默认隐藏）
        with ui.element('div').classes('content-block').style('display: none') as review_content:
            ui.label('价格、评分与平均评论数').classes('text-2xl font-bold mb-4')
            plotly3 = ui.plotly(plot_price_review(full_df)).classes('w-full h-150')
        # 筛选结果内容
        with ui.element('div').classes('content-block').style('display: none') as filtered_content:
            ui.label('筛选结果汇总').classes('text-2xl font-bold mb-4')
            plotly_filtered = ui.plotly(plot_filtered_summary(full_df)).classes('w-full h-96')
            # 筛选结果数据概览
            with ui.row().classes('w-full mt-4 gap-4') as stats_row:
                filtered_count_label = ui.label(f"筛选结果: {len(full_df)} 条记录").classes('text-lg font-bold')
                avg_price_label = ui.label(f"平均价格: ${full_df['price'].mean():.2f}").classes('text-lg font-bold')
                avg_review_label = ui.label(f"平均评分: {full_df['review rate number'].mean():.2f}/5").classes(
                    'text-lg font-bold')
        # 数据详情内容（默认隐藏）
        with ui.element('div').classes('content-block').style('display: none') as data_content:
            ui.label('筛选数据详情').classes('text-2xl font-bold mb-4')
            # 添加一个容器用于表格
            table_container = ui.element('div').classes('w-full overflow-auto h-[600px]')
            # 初始时创建全量数据表格
            create_data_table(full_df, table_container)
        # 统计分析内容（默认隐藏）
        with ui.element('div').classes('content-block').style('display: none') as stats_content:
            ui.label('数据集统计分析').classes('text-2xl font-bold mb-4')
            # 添加统计图表
            plotly_stats = ui.plotly(plot_statistical_analysis(stats_results)).classes('w-full h-[600px]')
            # 添加正态性检验结果
            with ui.card().classes('w-full mt-4'):
                ui.label('正态性检验结果').classes('text-xl font-bold mb-4')
                with ui.column().classes('w-full'):
                    for col, stats_data in stats_results.items():
                        if 'normality_p' in stats_data and stats_data['normality_p'] is not None:
                            with ui.element('div').classes('stat-card mb-4'):
                                ui.label(f"变量: {col}").classes('text-lg font-semibold')
                                ui.label(f"正态性检验p值: {stats_data['normality_p']:.4f}")
                                ui.label(f"是否正态分布: {'是' if stats_data['is_normal'] else '否'}")
                                ui.label(f"偏度: {stats_data['skewness']:.4f} (对称性)")
                                ui.label(f"峰度: {stats_data['kurtosis']:.4f} (尾部重量)")
        # 数据筛选器
        with ui.card().classes('w-full mt-4'):
            ui.label('数据筛选器').classes('text-xl font-bold mb-4')
            with ui.row().classes('w-full gap-4'):
                # 行政区筛选
                with ui.column().classes('w-1/4'):
                    ui.label('行政区')
                    neighborhood = ui.select(
                        options=['全部'] + sorted(full_df['neighbourhood group'].unique()),
                        value='全部',
                    )
                # 房型筛选
                with ui.column().classes('w-1/4'):
                    ui.label('房型')
                    room_type = ui.select(
                        options=['全部'] + sorted(full_df['room type'].unique()),
                        value='全部',
                    )
                # 价格范围筛选
                with ui.column().classes('w-1/4'):
                    ui.label('价格范围 ($)')
                    price_range = ui.slider(
                        min=int(full_df['price'].min()),
                        max=int(full_df['price'].max()),
                        value=(int(full_df['price'].min()), int(full_df['price'].max())),
                    )
                    price_label = ui.label(f"价格范围: {price_range.value[0]} - {price_range.value[1]}")
                # 评分范围筛选
                with ui.column().classes('w-1/4'):
                    ui.label('评分范围')
                    review_range = ui.slider(
                        min=1, max=5, value=(1, 5), step=0.1,
                    )
                    review_label = ui.label(f"评分范围: {review_range.value[0]:.1f} - {review_range.value[1]:.1f}")
            # 更新标签
            price_range.on('update:model-value', lambda e: price_label.set_text(
                f"价格范围: {e.value[0]} - {e.value[1]}"
            ))
            review_range.on('update:model-value', lambda e: review_label.set_text(
                f"评分范围: {e.value[0]:.1f} - {e.value[1]:.1f}"
            ))
            # 按钮组
            with ui.row().classes('w-full gap-4 mt-4'):
                apply_btn = ui.button('应用筛选', on_click=lambda: apply_filters(
                    neighborhood.value, room_type.value, price_range.value, review_range.value
                )).classes('w-1/3 bg-primary text-white')
                reset_btn = ui.button('重置筛选', on_click=lambda: reset_filters(
                    neighborhood, room_type, price_range, review_range, price_label, review_label, full_df
                )).classes('w-1/3 bg-gray-200')
                # 显示筛选数据按钮
                show_data_btn = ui.button('显示筛选数据', on_click=lambda: show_filtered_data(
                    neighborhood.value, room_type.value, price_range.value, review_range.value
                )).classes('w-1/3 bg-green-500 text-white')

    # 内容切换函数
    def show_content(content_name):
        # 隐藏所有内容块
        for content in [price_content, room_content, review_content, filtered_content, data_content, stats_content]:
            content.style('display: none')
        # 移除所有按钮的活跃状态
        for btn in [price_btn, room_btn, review_btn, filtered_btn, data_btn, stats_btn]:
            current_classes = btn._classes.copy() if hasattr(btn, '_classes') else []
            if 'active' in current_classes:
                current_classes.remove('active')
            btn.classes(' '.join(current_classes))
        # 显示当前内容块并激活对应按钮
        content_map = {
            'price': price_content,
            'room': room_content,
            'review': review_content,
            'filtered': filtered_content,
            'data': data_content,
            'stats': stats_content
        }
        button_map = {
            'price': price_btn,
            'room': room_btn,
            'review': review_btn,
            'filtered': filtered_btn,
            'data': data_btn,
            'stats': stats_btn
        }
        content_map[content_name].style('display: block')
        current_classes = button_map[content_name]._classes.copy() if hasattr(button_map[content_name],
                                                                              '_classes') else []
        if 'active' not in current_classes:
            current_classes.append('active')
        button_map[content_name].classes(' '.join(current_classes))
    def apply_filters(neighborhood, room_type, price, review):
        nonlocal current_filtered_df
        filtered_df = full_df.copy()
        # 行政区筛选
        if neighborhood != '全部':
            filtered_df = filtered_df[filtered_df['neighbourhood group'] == neighborhood]
        # 房型筛选
        if room_type != '全部':
            filtered_df = filtered_df[filtered_df['room type'] == room_type]
        # 价格筛选
        filtered_df = filtered_df[(filtered_df['price'] >= price[0]) & (filtered_df['price'] <= price[1])]
        # 评分筛选
        filtered_df = filtered_df[
            (filtered_df['review rate number'] >= review[0]) & (filtered_df['review rate number'] <= review[1])]
        # 更新当前筛选数据
        current_filtered_df = filtered_df
        # 更新筛选结果概览
        filtered_count_label.set_text(f"筛选结果: {len(filtered_df)} 条记录")
        if len(filtered_df) > 0:
            avg_price_label.set_text(f"平均价格: ${filtered_df['price'].mean():.2f}")
            avg_review_label.set_text(f"平均评分: {filtered_df['review rate number'].mean():.2f}/5")
        else:
            avg_price_label.set_text("平均价格: $0")
            avg_review_label.set_text("平均评分: 0/5")
        ui.notify(f"筛选完成: {len(filtered_df)} 条记录", type='positive')
        return filtered_df
    def show_filtered_data(neighborhood, room_type, price, review):
        filtered_df = apply_filters(neighborhood, room_type, price, review)
        # 更新所有图表
        plotly1.content = plot_price_distribution(filtered_df)
        plotly2.content = plot_room_type_price(filtered_df)
        plotly3.content = plot_price_review(filtered_df)
        plotly_filtered.content = plot_filtered_summary(filtered_df)
        # 更新数据详情表格
        create_data_table(filtered_df, table_container)
        # 切换到数据详情页面
        show_content('data')
        ui.notify("已更新所有图表和数据详情", type='info')
    def reset_filters(neighborhood, room_type, price_range, review_range, price_label, review_label, full_df):
        # 重置筛选控件
        neighborhood.value = '全部'
        room_type.value = '全部'
        price_range.value = (int(full_df['price'].min()), int(full_df['price'].max()))
        review_range.value = (1, 5)
        price_label.set_text(f"价格范围: {price_range.value[0]} - {price_range.value[1]}")
        review_label.set_text(f"评分范围: {review_range.value[0]:.1f} - {review_range.value[1]:.1f}")
        # 恢复原始图表
        plotly1.content = plot_price_distribution(full_df)
        plotly2.content = plot_room_type_price(full_df)
        plotly3.content = plot_price_review(full_df)
        plotly_filtered.content = plot_filtered_summary(full_df)
        # 更新数据详情表格为全量数据
        create_data_table(full_df, table_container)
        # 更新筛选结果概览
        filtered_count_label.set_text(f"筛选结果: {len(full_df)} 条记录")
        avg_price_label.set_text(f"平均价格: ${full_df['price'].mean():.2f}")
        avg_review_label.set_text(f"平均评分: {full_df['review rate number'].mean():.2f}/5")
        ui.notify("已重置所有筛选条件", type='info')
# 启动应用
if __name__ in {"__main__", "__mp_main__"}:
    create_web_interface()
    ui.run(title="Airbnb数据筛选分析", port=55666, reload=True)